package myJs

import myJs.Utils.{g, _}
import myJs.implicits.Implicits._
import myJs.myPkg.Implicits._
import myJs.myPkg.jquery._
import myJs.myPkg.{ColumnOptions, Select2Options, Swal, SwalOptions, TableOptions, TypeaheadOptions}
import org.scalajs.dom.ext.Ajax

import scala.collection.immutable.SeqMap
import scala.concurrent.ExecutionContext.Implicits.global
import scala.scalajs.js
import scala.scalajs.js.JSConverters._
import scala.scalajs.js.JSON
import scala.scalajs.js.annotation.{JSExport, JSExportTopLevel}
import myJs.myPkg.bootstrap.Bootstrap.default._
import org.scalajs.dom.{Element, Event, window}
import scalatags.Text.all.s


/**
 * Created by yz on 11/5/2020
 */
@JSExportTopLevel("Search")
object Search {

  val tableId = "table"
  val limit = 50


  @JSExport("init")
  def init = {
    refreshKeyword.zip(refreshJunctionType).zip(refreshAnnotation).zip(refreshTumorTypes).zip(refreshChr).map { x =>

    }
    bootStrapValidator

    $("a[data-toggle='tab']").on("shown.bs.tab", (y: Element, e: Event) => {
      refreshTable
    })

  }

  def tbFmt(columnName: String): js.Function = (v: js.Any, row: js.Dictionary[js.Any]) => columnName match {
    case _ => v
  }

  def refreshTumorTypes = {
    val url = g.jsRoutes.controllers.BrowseController.getAllTumorTypes().url.toString
    Ajax.get(url = s"${url}").map { xhr =>
      val data = JSON.parse(xhr.responseText).toJArS
      val array = data.map { geneType =>
        js.Dictionary("text" -> geneType, "id" -> geneType)
      }
      val options = Select2Options.multiple(true).allowClear(true).placeholder("click to choose").dictData(array)
      Tool.getInputByName("tumorTypes[]").select2(options)
    }
  }

  def bindEvt = {

  }

  def refreshKeyword = {
    val url = g.jsRoutes.controllers.SearchController.getAllGeneSymbols().url.toString
    Ajax.get(url = s"${url}").map { xhr =>
      val data = JSON.parse(xhr.responseText).toJArS
      Tool.getInputByName("keyword").typeahead("destroy").typeahead(TypeaheadOptions.source(data)
        .highlighter(Tool.highlighterF).updater(Tool.updater).matcher(Tool.matcher))
    }
  }

  def refreshJunctionType = {
    val url = g.jsRoutes.controllers.BrowseController.getAllJunctionTypes().url.toString
    Ajax.get(url = s"${url}").map { xhr =>
      val data = JSON.parse(xhr.responseText).toJArS
      val array = data.map { geneType =>
        js.Dictionary("text" -> geneType, "id" -> geneType)
      }
      val options = Select2Options.multiple(true).allowClear(true).placeholder("click to choose").dictData(array)
      Tool.getInputByName("junctionTypes[]").select2(options)
    }
  }

  @JSExport("showExample")
  def showExample(y: Element, name: String) = {
    val example = $(y).find("em").text().trim
    $(s"textarea[name='${name}']").`val`(example)
    $(s":input[name='${name}']").`val`(example)
    g.$(s"#${name}Form").formValidation("revalidateField", name)
  }

  @JSExport("keywordSearch")
  def keywordSearch = {
    $("#keywordForm").bootstrapValidator("revalidateField", "keyword")
    val bv = jQuery("#keywordForm").data("bootstrapValidator")
    bv.validate()
    val valid = bv.isValid().toB
    if (valid) {
      val index = layer.alert(Tool.loadingElement, Tool.layerOptions)
      val url = g.jsRoutes.controllers.SearchController.searchResultBefore().url.toString
      val keywords = Tool.getInputByName("keyword").`val`().toString.split(",")
      layer.close(index)
      if (keywords.size > limit) {
        Swal.swal(SwalOptions.title("Error").text(s"gene symbol is too many(must less than ${limit})!").`type`("error"))
      } else {
        window.location.href = s"${url}?keyword=${keywords.mkString(",")}"
      }

    }
  }

  def refreshTable = {
    $("#table").bootstrapTable("refresh")
  }

  @JSExport("myRun")
  def myRun = {
    val formId = "form"
    val bv = jQuery(s"#${formId}").data("bootstrapValidator")
    bv.validate()
    val valid = bv.isValid().toB
    if (valid) {
      val index = layer.alert(Tool.loadingElement, Tool.layerOptions)
      val url = g.jsRoutes.controllers.SearchController.advancedFilter().url.toString
      val formData = $(s"#${formId}").serialize()
      Ajax.post(url = s"${url}", data = formData, headers = Map("Content-Type" -> "application/x-www-form-urlencoded"),
        responseType = "application/json").map { xhr =>
        val geneSymbols = xhr.responseText.toJArS.take(limit)
        layer.close(index)
        if (geneSymbols.isEmpty) {
          Swal.swal(SwalOptions.title("Error").
            text(s"gene symbol is empty,please remove some filter condition!").`type`("error"))
        } else if (geneSymbols.size > limit) {
          Swal.swal(SwalOptions.title("Error").
            text(s"gene symbol is too many(must less than ${limit}),please add filter condition!").`type`("error"))
        } else {
          val hrefUrl = g.jsRoutes.controllers.SearchController.searchResultBefore().url.toString
          window.location.href = s"${hrefUrl}?keyword=${geneSymbols.mkString(",")}"
        }
      }
    }
  }

  def refreshAnnotation = {
    val url = g.jsRoutes.controllers.BrowseController.getAllAnnotation().url.toString
    Ajax.get(url = s"${url}").map { xhr =>
      val data = JSON.parse(xhr.responseText).toJArS
      val array = data.map { geneType =>
        js.Dictionary("text" -> geneType, "id" -> geneType)
      }
      val options = Select2Options.multiple(true).allowClear(true).placeholder("click to choose").dictData(array)
      Tool.getInputByName("annotations[]").select2(options)
    }
  }

  def refreshChr = {
    val url = g.jsRoutes.controllers.SearchController.getAllChr().url.toString
    Ajax.get(url = s"${url}").map { xhr =>
      val data = JSON.parse(xhr.responseText).toJArS.toList
      val array = (data).map { geneType =>
        js.Dictionary("text" -> geneType, "id" -> geneType)
      }.toJSArray
      val options = Select2Options.dictData(array)
      Tool.getInputByName("chr").select2(options)
    }
  }

  def bootStrapValidator = {
    val dict = js.Dictionary(
      "feedbackIcons" -> js.Dictionary(
        "valid" -> "glyphicon glyphicon-ok",
        "invalid" -> "glyphicon glyphicon-remove",
        "validating" -> "glyphicon glyphicon-refresh",
      ),
      "fields" -> js.Dictionary(
        "keyword" -> js.Dictionary(
          "validators" -> js.Dictionary(
            "notEmpty" -> js.Dictionary(
              "message" -> "keyword is required！"
            ),
          )
        ),
      )
    )
    g.$("#keywordForm").bootstrapValidator(dict)
    conditionBootStrapValidator
  }

  def conditionBootStrapValidator = {
    val infinityNumber = Int.MaxValue
    val dict = js.Dictionary(
      "feedbackIcons" -> js.Dictionary(
        "valid" -> "glyphicon glyphicon-ok",
        "invalid" -> "glyphicon glyphicon-remove",
        "validating" -> "glyphicon glyphicon-refresh",
      ),
      "fields" -> js.Dictionary(
        "start" -> js.Dictionary(
          "validators" -> js.Dictionary(
            "integer" -> js.Dictionary(
              "message" -> "Start Location must be an integer！"
            ),
            "between" -> js.Dictionary(
              "min" -> 1,
              "max" -> infinityNumber,
              "message" -> "Start Location must be greater than 0！",
            )
          )
        ),
        "end" -> js.Dictionary(
          "validators" -> js.Dictionary(
            "integer" -> js.Dictionary(
              "message" -> "End Location must be an integer！"
            ),
            "between" -> js.Dictionary(
              "min" -> 1,
              "max" -> infinityNumber,
              "message" -> "End Location must be greater than 0！",
            )
          )
        ),
      )
    )
    g.$("#condition #form").bootstrapValidator(dict)
  }


}
